﻿namespace FFF.Test.Application.DomainServices.FW
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Abp.Domain.Services;
    using Abp.Domain.Uow;
    using Abp.EntityFrameworkCore.Uow;
    using Abp.EntityFrameworkCore;
    using AutoMapper;
    using Abp.UI;
    using Ydm.Helper;
    using Ydm.Extensions;
    using Microsoft.EntityFrameworkCore;
    using AutoMapper.QueryableExtensions;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.Application.Repositories.FW;
    using FFF.Test.Entity.FW;
    using FFF.Test.Entity.FW.Dto;
    using FFF.Test.Entity.FW.View;

    /// <summary>
    /// 用户表领域层服务接口
    /// </summary>
    public class FWUserDomainService : YdmAbpDomainServiceBase, IFWUserDomainService
    {
        /// <summary>
        /// 用户表仓储
        /// </summary>
        private readonly IFWUserRepository _fWUserRepository;

        /// <summary>
        /// 角色用户中间仓储
        /// </summary>
        private readonly IFWStandardRole2USerRepository _fWStandardRole2USer;

        /// <summary>
        /// 标准角色表
        /// </summary>
        private readonly IFWStandardRoleRepository _fWStandardRoleRepository;

        /// <summary>
        /// The f w application repository
        /// </summary>
        private readonly IFWApplicationRepository _fWApplicationRepository;

        /// <summary>
        /// The f w function repository
        /// </summary>
        private readonly IFWFunctionRepository _fWFunctionRepository;

        /// <summary>
        /// The fwuserfunctionset repository
        /// </summary>
        private readonly IFWUserFunctionSetRepository _fWUserFunctionSetRepository;

        /// <summary>
        /// 系统和模块的中间表
        /// </summary>
        private readonly IFWApplication2ModuleRepository _fWApplication2ModuleRepository;

        /// <summary>
        /// Initializes a new instance of the <see cref="FWUserDomainService"/> class.
        /// 用户表领域层操作
        /// </summary>
        /// <param name="fWUserRepository">用户表仓储</param>
        /// <param name="fWStandardRole2USer">用户角色仓储</param>
        /// <param name="fWStandardRoleRepository">角色仓储</param>
        /// <param name="fWApplicationRepository">系统仓储</param>
        /// <param name="fWFunctionRepository">功能仓储</param>
        /// <param name="fWUserFunctionSetRepository">功能用户仓储</param>
        /// <param name="fWApplication2ModuleRepository">系统模块中间表</param>
        public FWUserDomainService(
            IFWUserRepository fWUserRepository,
            IFWStandardRole2USerRepository fWStandardRole2USer,
            IFWStandardRoleRepository fWStandardRoleRepository,
            IFWApplicationRepository fWApplicationRepository,
            IFWFunctionRepository fWFunctionRepository,
            IFWUserFunctionSetRepository fWUserFunctionSetRepository,
            IFWApplication2ModuleRepository fWApplication2ModuleRepository
        )
        {
            this._fWUserRepository = fWUserRepository;
            this._fWStandardRole2USer = fWStandardRole2USer;
            this._fWStandardRoleRepository = fWStandardRoleRepository;
            this._fWApplicationRepository = fWApplicationRepository;
            this._fWFunctionRepository = fWFunctionRepository;
            this._fWUserFunctionSetRepository = fWUserFunctionSetRepository;
            this._fWApplication2ModuleRepository = fWApplication2ModuleRepository;
        }

        /// <summary>
        /// 2.001 注册用户(于大明)
        /// </summary>
        /// <param name="inDto">注册用户输入dto</param>
        /// <returns>注册用户输出dto</returns>
        public async Task<RegisterUserOutDto> RegisterUserAsync(RegisterUserInDto inDto)
        {
            var userId = Guid.NewGuid();
            FWUserCreateInputDto inputDto = new FWUserCreateInputDto()
            {
                UserCode = inDto.Cellphone,
                UserPassword = inDto.Password,
                UserName = inDto.Nickname,
                Id = userId
            };

            await this._fWUserRepository.CreateByDtoAsync(inputDto);

            // 找到默认角色的id
            var roleId = await this._fWStandardRoleRepository.GetView().Where(x => x.StandardRoleName == "普通用户").Select(x => x.Id).FirstOrDefaultAsync();
            FWStandardRole2USerCreateInputDto role2USerCreateInputDto = new FWStandardRole2USerCreateInputDto()
            {
                StandardRoleGUID = roleId,
                UserGUID = userId
            };

            // 插入角色
            await this._fWStandardRole2USer.CreateByDtoAsync(role2USerCreateInputDto);

            var result = new RegisterUserOutDto();
            return result;
        }

        /// <summary>
        /// 1.004 获取站内模块信息(于大明)
        /// </summary>
        /// <param name="inDto">获取站内模块信息输入dto</param>
        /// <returns>获取站内模块信息输出dto</returns>
        public async Task<GetUserSetFunctionOutDto> GetUserSetFunctionAsync(GetUserSetFunctionInDto inDto)
        {
            var viewAppliction = this._fWApplicationRepository.GetView();
            var viewFunction = this._fWFunctionRepository.GetView();
            var viewFunctionSet = this._fWUserFunctionSetRepository.GetView();
            var viewApplication2Module = this._fWApplication2ModuleRepository.GetView();

            GetUserSetFunctionOutDto result = new GetUserSetFunctionOutDto();
            result.UserSetModuleMyApplications = await viewAppliction
                .OrderBy(x => x.ApplicationOrderCode)
                .ProjectTo<UserSetModuleMyApplication>().ToListAsync();
            result.UserSetModuleMyMudules = await viewApplication2Module
                .OrderBy(x => x.A2MOrderCode)
                .ProjectTo<UserSetModuleMyModule>().ToListAsync();

            result.ChooseMyFunctions = await viewFunction.Join(
                viewFunctionSet.Where(x => x.UserGUID == inDto.UserGUID),
                x => x.Id,
                y => y.FunctionGUID,
                (x, y) => new ChooseMyFunction
                {
                    Id = x.Id,
                    FunctionName = y.UserFunctionSetName,
                    ModuleGUID = x.ModuleGUID,
                    FunctionOrderCode = x.OrderCode,
                }).OrderBy(x => x.FunctionOrderCode).ToListAsync();

            // 先拿到所有的父级节点
            result.UserSetModuleMyFunctions = await viewFunction.Where(x => x.ParentGUID == null)
                .OrderBy(x => x.ModuleGUID)
                .ThenBy(x => x.OrderCode)
                .ProjectTo<UserSetModuleMyFunction>().ToListAsync();

            // 找到每个父级节点下面的子节点
            foreach (UserSetModuleMyFunction functionItem in result.UserSetModuleMyFunctions)
            {
                functionItem.MyChildFuntion = await viewFunction
                    .Where(x => x.ParentGUID == functionItem.Id)
                    .OrderBy(x => x.OrderCode)
                    .ProjectTo<UserSetModuleMyFunction>().ToListAsync();

                // 判断下是否为选中的状态
                functionItem.MyChildFuntion.ForEach(item =>
                {
                    if (result.ChooseMyFunctions.Any(x => x.Id == item.Id))
                    {
                        item.IsChoose = 1;
                    }
                });
            }

            return result;
        }
    }
}
